package utils;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import beans.*;
import net.sf.json.xml.XMLSerializer;
import org.apache.commons.io.IOUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import dao.AlgorithmDao;


public class XmlUtil {

    /**
     * @return uri of the new parameters xml file(with parameters' values)
     * @throws IOException
     */
    public GenerateXmlUriResult generateParamsXml(String executeAlgorithmFileName, RunnableAlgorithm runnableAlgorithm, Map<String, PhysicalBlockInfor> params, String blockPrefix) throws IOException {
//		for(Map.Entry<String, PhysicalBlockInfor> one:params.entrySet()){
//			Log4jInit.logger.info(one.getKey()+":"+one.getValue().toString());
//		}
        GenerateXmlUriResult resultData = new GenerateXmlUriResult();
        Map<String, String> inputMap = new HashMap<>();
        Map<String, String> outputMap = new HashMap<>();
        Map<String, String> paramMap = new HashMap<>();
        XStream result = new XStream(new DomDriver("utf-8"));
        result.alias("Algorithm", XmlParams.class);
        result.alias("parameters", XmlParameters.class);
       // result.aliasField("AlgorithmInputs", XmlParameters.class, "algorithmInputs");
        result.aliasField("InputFiles", XmlParameters.class, "InputFiles");
        result.aliasField("AlgorithmOutputs", XmlParameters.class, "algorithmOutputs");
        result.aliasField("AlgorithmParams", XmlParameters.class, "algorithmParams");
        result.alias("file", XmlFile.class);
        result.alias("InputParam", XmlAlgorithmParam.class);
        result.alias("AlgorithmOutput", XmlAlgorithmOutput.class);
        result.autodetectAnnotations(true);
//		StringBuilder gg = new StringBuilder();
//		BufferedReader br = new BufferedReader(new FileReader(new File(xmlUri)));
//		String tempString = null;
//		while((tempString = br.readLine())!=null){
//			gg.append(tempString);
//		}
//		br.close();
        XmlParams convert = new XmlParams();
        XmlParameters parameters = new XmlParameters();
        AlgorithmDao algorithmDao = new AlgorithmDao();
        AlgorithmDetail algorithmDetail = algorithmDao.getAlgorithmDetailWithoutUserId(runnableAlgorithm.getAlgorithmDetail().getId() + "");
        HashMap<String, String> paramValues = runnableAlgorithm.paramValues;
        ArrayList<XmlFile> inputFiles = new ArrayList<>();
        ArrayList<XmlAlgorithmParam> inputParams = new ArrayList<>();
        ArrayList<XmlAlgorithmOutput> outputs = new ArrayList<>();
//		String execNodes = "";																	//without physical blocks
        for (AlgorithmInput input : algorithmDetail.getAlgorithmInputs()) {
            XmlFile inputFile = new XmlFile();
            inputFile.setFileIntroduction(input.getInputIntroduction());
            inputFile.setFileParam(input.getInputName());
            inputFile.setValue(params.get(blockPrefix + input.getInputName()).getBlk());
            inputFile.setFileType("");
            inputFile.setSuffix("");
            inputFiles.add(inputFile);

            //2018-7-26添加，此时直接将输入输出返回给algorithmThread，省的到时候再解析xml文件
            inputMap.put(inputFile.getFileParam(), inputFile.getValue());
        }
//		execNodes = execNodes.substring(0, execNodes.lastIndexOf(" "));							//without physical blocks
        for (AlgorithmParam param : algorithmDetail.getAlgorithmParams()) {
            XmlAlgorithmParam inputParam = new XmlAlgorithmParam();
            inputParam.setParamIntroduction(param.getParamIntroduction());
            inputParam.setParam(param.getParamSymbol());
            inputParam.setParamType(param.getParamType());
            inputParam.setValue(paramValues.get(param.getParamSymbol()));
            inputParams.add(inputParam);

            //2018-7-26添加，此时直接将输入输出返回给algorithmThread，省的到时候再解析xml文件
            paramMap.put(inputParam.getParam(), inputParam.getValue());
        }
        for (AlgorithmOutput output : algorithmDetail.getAlgorithmOutputs()) {
            XmlAlgorithmOutput outputt = new XmlAlgorithmOutput();
            outputt.setOutputIntroduction(output.getOutputIntroduction());
            outputt.setOutputName(output.getOutputName());
            //	outputt.setValue(params.get(blockPrefix+output.getOutputName()+"_output").getBlk());
            outputt.setValue(params.get(blockPrefix + output.getOutputName()).getBlk());
            outputt.setSuffix("");
            outputt.setOutputType("");
            outputs.add(outputt);

            //2018-7-26添加，此时直接将输入输出返回给algorithmThread，省的到时候再解析xml文件
            outputMap.put(outputt.getOutputName(), outputt.getValue());
        }
        //	parameters.setInputFiles(inputFiles);
        parameters.setAlgorithmInputs(inputFiles);
        /**
         * 这里的if判断作用：可能存在的无算法执行参数的情况，这里的inputParams的size可能为零，
         * 但是在产生的xml字符串里面会多出一个<AlgorithmParams/>，所以这里需要加一个判断，能达到size为零时没有那个东西
         */
        if (runnableAlgorithm.getAlgorithmDetail().getAlgorithmParams().size() > 0) {
            parameters.setAlgorithmParams(inputParams);
        }
        parameters.setAlgorithmOutputs(outputs);
        convert.setParameters(parameters);
        String xmlResult = result.toXML(convert);
//		XMLSerializer xml = new XMLSerializer();
//		JSON josn =xml.read(xmlResult);
//		Log4jInit.logger.info("josn:::"+josn.toString());
        String uri = algorithmDetail.getLocationUri();
        String newUri = uri.substring(0, uri.lastIndexOf("/") + 1);
        String xmlName = uri.substring(uri.lastIndexOf("/") + 1);
        String xmlNameWithUUID = xmlName + "_ParamsXmlWithValueForOneJob_" + UUID.randomUUID().toString().substring(0, 20) + ".xml";
        xmlName = xmlName.substring(0, xmlName.lastIndexOf(".")) + ".xml";
        //下面就是统一将文件名称设置为uuid
//		xmlName = executeAlgorithmFileName +".xml";
        File directory = new File(newUri);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        FileWriter fw = new FileWriter(newUri + xmlNameWithUUID);
        fw.write(xmlResult);
        fw.close();
        resultData.setParamsXmlFilePathUri(xmlName);
        resultData.setParamsXmlFilePathUriWithUUID(newUri + xmlNameWithUUID);
        resultData.setInputMap(inputMap);
        resultData.setOutputMap(outputMap);
        resultData.setParamMap(paramMap);
//		resultData.setExecNodes(execNodes);												//without physical blocks
//		Log4jInit.logger.info("xml uri:"+resultData.getParamsXmlFilePathUri());
        return resultData;

    }

    public JSONObject parseXMLFiletoJson(File f) {

        JSONObject rtObj = null;
        if (f != null && f.isFile()) {
            try {
                InputStream is = new FileInputStream(f);
                String xml = IOUtils.toString(is);
                rtObj = XML.toJSONObject(xml);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return rtObj;
    }

    /**
     * 返回值map:<输入名称，具体的值>
     *
     * @param xmlJsonObject
     * @return
     */
    public Map<String, String> parseInputValue(JSONObject xmlJsonObject) throws JSONException {
        Map<String, String> result = new HashMap<>();
        try {
            /*String value = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("InputFiles")
                    .getJSONObject("file").getString("value").replaceAll("\\\\","/");
			String name = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("InputFiles")
					.getJSONObject("file").getString("fileParam");*/
            String value = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmInputs")
                    .getJSONObject("file").getString("value").replaceAll("\\\\", "/");
            String name = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmInputs")
                    .getJSONObject("file").getString("fileParam");
            result.put(name, value);
        } catch (JSONException e) {
            /*org.json.JSONArray files = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").
                    getJSONObject("InputFiles").getJSONArray("file");*/
            org.json.JSONArray files = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").
                    getJSONObject("AlgorithmInputs").getJSONArray("file");
            for (int in = 0; in < files.length(); in++) {
                result.put(files.getJSONObject(in).getString("fileParam"), files.getJSONObject(in).getString("value").replaceAll("\\\\", "/"));
            }
        }
        return result;
    }

    /**
     * 返回值map:<输出名称，具体的值>
     *
     * @param xmlJsonObject
     * @return
     */
    public Map<String, String> parseOutputValue(JSONObject xmlJsonObject) throws JSONException {
        Map<String, String> result = new HashMap<>();
        try {
            String value = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmOutputs")
                    .getJSONObject("AlgorithmOutput").getString("value").replaceAll("\\\\", "/");
            String name = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmOutputs")
                    .getJSONObject("AlgorithmOutput").getString("outputName");
            result.put(name, value);
        } catch (JSONException e) {
            org.json.JSONArray files = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").
                    getJSONObject("AlgorithmOutputs").getJSONArray("AlgorithmOutput");
            for (int in = 0; in < files.length(); in++) {
                result.put(files.getJSONObject(in).getString("outputName"), files.getJSONObject(in).getString("value").replaceAll("\\\\", "/"));
            }
        }
        return result;
    }

    /**
     * 返回值map:<参数名称，具体的值>
     *
     * @param xmlJsonObject
     * @return
     */
    public Map<String, String> parseParamValue(JSONObject xmlJsonObject) throws JSONException {
        Map<String, String> result = new HashMap<>();
        if (xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").isNull("AlgorithmParams")) {
            return null;
        }
        try {
            String value = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmParams")
                    .getJSONObject("InputParam").getString("value");
            String name = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").getJSONObject("AlgorithmParams")
                    .getJSONObject("InputParam").getString("param");
            result.put(name, value);
        } catch (JSONException e) {
            org.json.JSONArray files = xmlJsonObject.getJSONObject("Algorithm").getJSONObject("parameters").
                    getJSONObject("AlgorithmParams").getJSONArray("InputParam");
            for (int in = 0; in < files.length(); in++) {
                result.put(files.getJSONObject(in).getString("param"), files.getJSONObject(in).getString("value"));
            }
        }
        return result;
    }

    public String saveJson2XML(String jobId, String json) {
        net.sf.json.JSONObject jobj = net.sf.json.JSONObject.fromObject(json);
        // JSON jsonObject = JSONSerializer.toJSON(json);
        String xml = new XMLSerializer().write(jobj);
        String filePath = HttpConfig.jobFileXml+jobId+".xml";
//        String filePath = "D:\\"+jobId+".xml";
        File file = new File(filePath); // 找到File类的实例
        if (json == null){
            return null;
        }
        try {
            if (!file.exists()){
                file.createNewFile();
            }
            Writer out =new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
            // 写入数据
            out.write(xml);
            out.flush();
            // 保存数据
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath;
    }

    public static void main(String[] args) throws JSONException {
        XmlUtil xmlUtil = new XmlUtil();
        String paramXmlFileUri = "/home/beirut/Documents/code/362/idea_ParamsXmlWithValueForOneJob_6a0718be-e526-40b3-a.xml";
        Log4jInit.logger.info(xmlUtil.parseXMLFiletoJson(new File(paramXmlFileUri)).getJSONObject("Algorithm").getJSONObject("parameters").isNull("fhkshdfk")+"");
    }
}

